package com.yuyou.fn.educational.discount;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.Utils;
import groovy.lang.GroovyClassLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by wens on 2017/7/24.
 */
public class ExecuteServiceProxy {

    private static String TPL =
            "import java.util.*;\n" +
            "import java.math.*;\n" +
            "import com.yuyou.fn.educational.discount.*;\n" +
            "import com.yuyou.fn.educational.entity.*;\n" +
            "import static com.yuyou.fn.common.util.BeanUtils.*;\n" +
            "import static com.yuyou.fn.common.util.Utils.*;\n" +
            "\n" +
            "\n" +
            "class ExecuteServiceImpl implements IExecuteService {\n" +
            "\n" +
            "\nstatic Map parsePeriodParams(period){\n" +
            "        def map = [:]\n" +
            "\n" +
            "        period.split(\",\").each {\n" +
            "            def items  = it.split(\"#\") as ArrayList\n" +
            "\n" +
            "            if(items.size() == 1 ){\n" +
            "                map[items[0]] = [\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\"] as ArrayList\n" +
            "            }else{\n" +
            "                map[items[0]] = items.subList(1,items.size())\n" +
            "            }\n" +
            "        }\n" +
            "        return map\n" +
            "    }" +
            "\n" +
            "    @Override\n" +
            "    DiscountResultSet execute(List<DiscountRegCourseClass> discountRegCourseClassList, Map<String, Object> params, Helper helper) {\n" +
            "        //function\n" +
            "    }\n" +
            "}";

    private static final Logger LOG = LoggerFactory.getLogger(ExecuteServiceProxy.class);

    private static LoadingCache<String,IExecuteService> EXECUTE_SERVICES = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.DAYS ).build(new CacheLoader<String, IExecuteService>() {
        @Override
        public IExecuteService load(String key) throws Exception {
            GroovyClassLoader groovyCl = new GroovyClassLoader();
            Class aClass = groovyCl.parseClass(TPL.replace("//function", key ));
            try {
                IExecuteService executeService  = (IExecuteService) aClass.newInstance();
                return executeService ;
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    });

    private String calFunction ;

    private String params;

    private Helper helper ;


    public ExecuteServiceProxy(String calFunction , String params , Helper helper ){
        this.calFunction = calFunction ;
        this.params  = params ;
        this.helper = helper ;
    }


    public DiscountResultSet execute(List<DiscountRegCourseClass> regCourseClassList ) {
        try {
            IExecuteService executeService = EXECUTE_SERVICES.get(this.calFunction);
            return executeService.execute(regCourseClassList, getParams() , this.helper );
        } catch (Exception e) {
            LOG.error("Execute cal fail", e );
            throw new BusException("Execute cal fail" , e );
        }

    }

    public Map<String,Object> getParams() {
        JSONArray jsonArray = JSONArray.parseArray(params);
        Map<String,Object> p = new HashMap<>();
        for(int i = 0 ; i < jsonArray.size() ;i++ ){
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            p.put(jsonObject.getString("name") ,getValue(jsonObject));
        }
        return p;
    }

    private Object getValue(JSONObject jsonObject) {
        String type = jsonObject.getString("type");
        String value = jsonObject.getString("value");
        if("string".equals(type)){
            return value ;
        }else if("int".equals(type)){
            return Integer.valueOf(value);
        }else if("float".equals(type)){
            return Float.valueOf(value);
        }else if("date".equals(type)){
            return Utils.parseDate(value,"yyyy-MM-dd");
        }else{
            throw new BusException("Unsupported type["+type+"]");
        }
    }


}
